package com.dualsportmaps.android.views;

import java.util.ArrayList;
import java.util.List;

import net.osmand.LogUtil;
import net.osmand.OsmAndFormatter;
import net.osmand.data.Amenity;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.PoiFilter;
import com.dualsportmaps.android.R;
import net.osmand.plus.ResourceManager;
import net.osmand.plus.render.RenderingIcons;
import net.osmand.plus.views.OsmandMapLayer;
import net.osmand.plus.views.OsmandMapTileView;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.util.DisplayMetrics;
import android.view.WindowManager;

import com.dualsportmaps.android.DsmResourceManager;

public class DsmPOIMapLayer implements OsmandMapLayer {
	private static final int startZoom = 10;
	public static final int LIMIT_POI = 200;
	public static final org.apache.commons.logging.Log log = LogUtil.getLog(DsmPOIMapLayer.class);
	
	
	private Paint pointAltUI;
	private Paint point;
	private OsmandMapTileView view;
	private List<Amenity> objects = new ArrayList<Amenity>();

	private ResourceManager resourceManager;
	private PoiFilter filter;
	private DisplayMetrics dm;
	
	@Override
	public boolean onLongPressEvent(PointF point) {
		return false;
	}
	
	public PoiFilter getFilter() {
		return filter;
	}
	
	public void setFilter(PoiFilter filter) {
		this.filter = filter;
	}
	
	public Amenity getAmenityFromPoint(PointF point){
		Amenity result = null;
		if (objects != null) {
			int ex = (int) point.x;
			int ey = (int) point.y;
			int radius = getRadiusPoi(view.getZoom()) * 3 / 2;
			try {
				for (int i = 0; i < objects.size(); i++) {
					Amenity n = objects.get(i);
					int x = view.getRotatedMapXForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude());
					int y = view.getRotatedMapYForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude());
					if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) {
						radius = Math.max(Math.abs(x - ex), Math.abs(y - ey));
						result = n;
					}
				}
			} catch (IndexOutOfBoundsException e) {
				// that's really rare case, but is much efficient than introduce synchronized block
			}
		}
		return result;
	}
	

	@Override
	public boolean onTouchEvent(PointF point) {
		final Amenity n = getAmenityFromPoint(point);
		if(n != null){
			String format = OsmAndFormatter.getPoiSimpleFormat(n, view.getContext(), OsmandSettings.usingEnglishNames(view.getSettings()));
//			Toast.makeText(view.getContext(), format, Toast.LENGTH_SHORT).show();
			AlertDialog.Builder dialog = new AlertDialog.Builder(view.getContext());
			Bitmap poi = getPOIBitmap(n);
			if(poi != null)
				dialog.setIcon(new BitmapDrawable(poi));
			dialog.setTitle(format);
			
			String message = "";
			if(n.getOpeningHours() != null){
				message += "\n" + view.getContext().getString(R.string.opening_hours) +" : "+ n.getOpeningHours();
			}
			if(n.getPhone() != null){
				message += "\n" + view.getContext().getString(R.string.phone) +" : "+ n.getPhone(); 
			}
			if(n.getSite() != null){
				message += "\n" + view.getContext().getString(R.string.website) +" : "+ n.getSite(); 
			}
			if(message.length() > 0)
				dialog.setMessage(message);
			dialog.setNeutralButton("Route To", new DialogInterface.OnClickListener(){

				@Override
				public void onClick(DialogInterface dialog, int which) {
					try {
						DsmResourceManager.getMapActivity().navigateToPoint(n.getLocation());
						DsmResourceManager.getMapActivity().getDirectionsFromCurrentLocation();
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}});
			
			final AlertDialog d = dialog.create();
			d.show();
			new Thread(new Runnable() {

				@Override
				public void run() {
					try {
						Thread.sleep(2500);
						d.dismiss();
					} catch (InterruptedException e) {
					}
				}}).start();
			return true;
		}
		return false;
	}
	
	
	@Override
	public void initLayer(OsmandMapTileView view) {
		this.view = view;
		dm = new DisplayMetrics();
		WindowManager wmgr = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE);
		wmgr.getDefaultDisplay().getMetrics(dm);

		pointAltUI = new Paint();
		pointAltUI.setColor(Color.rgb(255, 128, 0));
		pointAltUI.setAlpha(160);
		pointAltUI.setStyle(Style.FILL);
		
		point = new Paint();
		point.setColor(Color.GRAY);
		point.setAntiAlias(true);
		point.setStyle(Style.STROKE);
		resourceManager = view.getApplication().getResourceManager();
	}
	
	public int getRadiusPoi(int zoom){
		int r = 0;
		if(zoom < startZoom){
			r = 0;
		} else if(zoom <= 15){
			r = 10;
		} else if(zoom == 16){
			r = 14;
		} else if(zoom == 17){
			r = 16;
		} else {
			r = 18;
		}
		return (int) (r * dm.density);
	}

	@Override
	public void onDraw(Canvas canvas, RectF latLonBounds, boolean nightMode) {
		if (view.getZoom() >= startZoom) {
			objects.clear();
			resourceManager.searchAmenitiesAsync(latLonBounds.top, latLonBounds.left, latLonBounds.bottom, latLonBounds.right, view.getZoom(), filter, objects);
			int r = getRadiusPoi(view.getZoom());
			for (Amenity o : objects) {
				int[] ps = view.getRotatedMapPoints(o.getLocation().getLatitude(),o.getLocation().getLongitude());
				int x = ps[0];
				int y = ps[1];
				Integer icon = RenderingIcons.getIcons().get(o.getSubType());
				if(icon == null) {
					canvas.drawCircle(x, y, r, pointAltUI);
					canvas.drawCircle(x, y, r, point);
				} else {
					Bitmap iconBitmap = BitmapFactory.decodeResource(view.getResources(), icon);
					canvas.drawBitmap(iconBitmap, x-iconBitmap.getWidth()/2, y-iconBitmap.getHeight()/2, null);
					iconBitmap.recycle();
					iconBitmap = null;
				}
			}
		}
	}

	private Bitmap getPOIBitmap(Amenity amenity) {
		Integer icon = RenderingIcons.getIcons().get(amenity.getSubType());
		if(icon != null) {
			return BitmapFactory.decodeResource(view.getResources(), icon);
		}
		return null;
	}
	
	@Override
	public void destroyLayer() {
		
	}

	@Override
	public boolean drawInScreenPixels() {
		return true;
	}

}
